home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume3 / proto < prev    next >
Encoding:
Text File  |  1989-02-03  |  17.3 KB  |  729 lines

  1. Path: xanth!mcnc!rutgers!cmcl2!husc6!necntc!ncoast!allbery
  2. From: dcw@doc.ic.ac.uk (Duncan White)
  3. Newsgroups: comp.sources.misc
  4. Subject: v03i045: ANSI prototypes builder for C.
  5. Message-ID: <8806072033.aa05024@tgould.doc.ic.ac.uk>
  6. Date: 12 Jun 88 21:28:44 GMT
  7. Sender: allbery@ncoast.UUCP
  8. Reply-To: dcw@doc.ic.ac.uk (Duncan White)
  9. Lines: 717
  10. Approved: allbery@ncoast.UUCP
  11.  
  12. comp.sources.misc: Volume 3, Issue 45
  13. Submitted-By: "Duncan White" <dcw@doc.ic.ac.uk>
  14. Archive-Name: proto
  15.  
  16.     A couple of months ago, I mentioned on the news that I had
  17.     written a prototype builder for C.  Several people mailed
  18.     me requesting it, but I never got around to sending it to
  19.     them.
  20.  
  21.     A couple of days ago, I modified the source to allow the user
  22.     to print out a pretty printed form of the functions recognised,
  23.     which seems like a useful option to have!
  24.  
  25.     Anyway, I wondered if you'd like to post the source into
  26.     comp.sources.misc ....  the code should run on almost any
  27.     machine... it certainly compiles and runs fine on an Atari ST
  28.     with Lattice C 3.04, on a PC with Microsoft 4.0, and BSD4.2
  29.     and 4.3 Unix with standard Unix C.
  30.  
  31.     [Of course, on standard Unix compilers, it is a rather
  32.     pointless : but I develop on Unix and the ST, so appreciate
  33.     the ability to prototype on either machine...]
  34.  
  35.         Duncan White
  36.  
  37. ----------------- Cut here ----------------------- Cut here -------------
  38. #! /bin/sh
  39. # This is a shell archive, meaning:
  40. # 1. Remove everything above the #! /bin/sh line.
  41. # 2. Save the resulting text in a file.
  42. # 3. Execute the file with /bin/sh (not csh) to create the files:
  43. #    Makefile
  44. #    dcw.h
  45. #    dcwos.h
  46. #    proto.1
  47. #    proto.c
  48. #    testproto
  49. # This archive created: Tue Jun  7 20:26:55 1988
  50. export PATH; PATH=/bin:$PATH
  51. echo shar: extracting "'Makefile'" '(62 characters)'
  52. if test -f 'Makefile'
  53. then
  54.     echo shar: will not over-write existing file "'Makefile'"
  55. else
  56. cat << \SHAR_EOF > 'Makefile'
  57. proto:    proto.c
  58.     cc -o proto proto.c
  59.  
  60. clean:
  61.     /bin/rm -f proto
  62. SHAR_EOF
  63. if test 62 -ne "`wc -c < 'Makefile'`"
  64. then
  65.     echo shar: error transmitting "'Makefile'" '(should have been 62 characters)'
  66. fi
  67. fi # end of overwriting check
  68. echo shar: extracting "'dcw.h'" '(1306 characters)'
  69. if test -f 'dcw.h'
  70. then
  71.     echo shar: will not over-write existing file "'dcw.h'"
  72. else
  73. cat << \SHAR_EOF > 'dcw.h'
  74. /*
  75.  *    My standard include file
  76.  *
  77.  ********* History:
  78.  *
  79.  *    Version    Who    Date        Comments
  80.  *    =======    ===    ====        ========
  81.  *    1.3.3    dcw    6th June 1988    Made BOOL & BOOLEAN char, not int!!
  82.  *    1.3.2    dcw    26th Apr 1988    Added NOC_ALLOC, NOC_NEW, made
  83.  *                    COPYOF call NOC_ALLOC !!!
  84.  *    1.3.1    dcw    2nd Mar 1988    Changed name to dcw.h and dcwos.h
  85.  *                    included strings.h and ctype.h
  86.  *                    added extern calloc() decln
  87.  *    1.3    dcw    9th Sep 1987    Included os.h
  88.  *    1.2    dcw    19th July 1987    Made external 'extern' [was null]
  89.  *                    and added brackets in streq
  90.  *    1.1    dcw    2nd July 1987    Added BOOLEAN as well as BOOL !
  91.  *    1.0    dcw    10th June 1987    Wrote it.
  92.  */
  93.  
  94.  
  95. #include <stdio.h>
  96. #include <strings.h>
  97. #include <ctype.h>
  98. #include "dcwos.h"
  99.  
  100. extern char *calloc(), malloc();
  101.  
  102. #define ASSERT(x,y) if(!(x)){printf y;exit(1);}
  103. #define ABORT(y)    ASSERT(FALSE,y)
  104. #define FORWARD
  105. #define EXTERNAL    extern
  106.  
  107. #define ALLOC(n,t) (t *)calloc((n),sizeof(t))
  108. #define NEW(t)     ALLOC(1,t)
  109.  
  110. /* make copy of old string into new: was ALLOC not NOC_ALLOC */
  111. #define COPYOF(new,old)  {new=NOC_ALLOC(1+strlen(old),char);strcpy(new,old);}
  112.  
  113. #define NOC_ALLOC(n,t) (t *)malloc((n)*sizeof(t))
  114. #define NOC_NEW(t)     NOC_ALLOC(1,t)
  115.  
  116. #define streq(x,y)  (strcmp((x),(y))==0)
  117.  
  118. #define BOOL    char
  119. #define BOOLEAN char
  120. #define TRUE    1
  121. #define FALSE   0
  122. SHAR_EOF
  123. if test 1306 -ne "`wc -c < 'dcw.h'`"
  124. then
  125.     echo shar: error transmitting "'dcw.h'" '(should have been 1306 characters)'
  126. fi
  127. fi # end of overwriting check
  128. echo shar: extracting "'dcwos.h'" '(279 characters)'
  129. if test -f 'dcwos.h'
  130. then
  131.     echo shar: will not over-write existing file "'dcwos.h'"
  132. else
  133. cat << \SHAR_EOF > 'dcwos.h'
  134. /*
  135.  * Alter this to show which o/s you have
  136.  */
  137.  
  138. #define UNIX
  139. #undef ATARIST
  140. #undef MSDOS
  141.  
  142. /*
  143.  * Alter this to show which compiler you have:
  144.  */
  145.  
  146. #define UNIXC
  147. #undef LATTICE304
  148. #undef MICROSOFT4
  149.  
  150. /*
  151.  * Define this only if your compiler supports prototypes
  152.  */
  153.  
  154. #undef HASPROTOS
  155. SHAR_EOF
  156. if test 279 -ne "`wc -c < 'dcwos.h'`"
  157. then
  158.     echo shar: error transmitting "'dcwos.h'" '(should have been 279 characters)'
  159. fi
  160. fi # end of overwriting check
  161. echo shar: extracting "'proto.1'" '(1489 characters)'
  162. if test -f 'proto.1'
  163. then
  164.     echo shar: will not over-write existing file "'proto.1'"
  165. else
  166. cat << \SHAR_EOF > 'proto.1'
  167. .EV
  168. .T1 proto 1 "2/6/88"
  169. .SH NAME
  170. proto \- build ANSI style prototypes from C source code.
  171. .SH SYNTAX
  172. .B proto
  173. [\fB\-f\fP]  \fIinputfile\fP [\fIoutputfile\fp]
  174. .SH DESCRIPTION
  175. .I Proto
  176. builds a list of ANSI-style external declarations [\fIprototypes\fP] for all
  177. the functions in a given C source file.
  178. It produces this list in two forms:
  179. .nf
  180.     #ifdef HASPROTOS
  181.     <nice external prototype declarations>
  182.     #else
  183.     <old ikky external declarations for UNIX C compilers>
  184.     #endif
  185. .fi
  186. .PP
  187. You can then incorporate the file generated into your .h files.
  188. Make sure you #define HASPROTOS iff your compiler supports
  189. prototypes: otherwise you'll lose all the advantages.
  190. .PP
  191. If you omit the output file from the command line,
  192. the standard output will be used.
  193. .SH OPTIONS
  194. The only option this program accepts is \fB-f\fP,
  195. which causes it to place a pretty-printed form of the
  196. original function declarations in the output file,
  197. rather than the prototypes.
  198. .SH PORTABILITY
  199. This program should work fine on any system with a C compiler.
  200. If it doesn't, please let me know!
  201. .SH AUTHOR
  202. Duncan White,
  203. Dept Of Computing,
  204. Imperial College,
  205. London,
  206. England.
  207. .SH LIMITATIONS
  208. The grammar used for parsing is incomplete.
  209. In particular, array parameters, function parameters, and structure parameters
  210. not disguised by \fI#define's\fP or \fItypedef's\fP will not be recognised.
  211. .PP
  212. In addition, the entire function declaration, including the types of the
  213. parameters, must reside on a single line for it to be recognised.
  214. SHAR_EOF
  215. if test 1489 -ne "`wc -c < 'proto.1'`"
  216. then
  217.     echo shar: error transmitting "'proto.1'" '(should have been 1489 characters)'
  218. fi
  219. fi # end of overwriting check
  220. echo shar: extracting "'proto.c'" '(10332 characters)'
  221. if test -f 'proto.c'
  222. then
  223.     echo shar: will not over-write existing file "'proto.c'"
  224. else
  225. cat << \SHAR_EOF > 'proto.c'
  226. /*
  227.  *            Prototypes builder...
  228.  *            =====================
  229.  *
  230.  *        Copyright (C) Duncan White, 1987 & 1988.
  231.  *
  232.  ****** Restrictions on use
  233.  *
  234.  *    Anyone may use, adapt and extend this program in any way they like,
  235.  *    subject to the following:
  236.  *
  237.  *    1).    my name is not removed.
  238.  *    2).    your name is appended if you change it, detailing the changes
  239.  *        you made.
  240.  *    3).    you don't make any money out of it without consulting me.
  241.  *    4).    you don't attempt to alter this 'restrictions on use' section.
  242.  *
  243.  *    In other words, share & enjoy...
  244.  *
  245.  ****** Purpose
  246.  *
  247.  *    This program attempts to build a file of external declarations
  248.  *    [prototypes] for all the functions declared in a given C file.
  249.  *    It produces this list in two forms:
  250.  *
  251.  *    #ifdef HASPROTOS
  252.  *    <nice external prototype declarations>
  253.  *    #else
  254.  *    <old ikky external declarations for UNIX C compilers>
  255.  *    #endif
  256.  *
  257.  *    You can then incorporate the file generated into your .h files.
  258.  *    Make sure you #define HASPROTOS iff your compiler supports
  259.  *    prototypes: otherwise you'll lose all the advantages.
  260.  *
  261.  *    Alternatively, if you give the -f [function] option, the program will
  262.  *    instead produce a pretty printed text form of the function
  263.  *    declarations it parses.
  264.  *
  265.  ****** How does it do it:
  266.  *
  267.  *    The program parses EACH LINE of a C source file to see whether it
  268.  *    satisfies the grammar shown below. If it does, the appropriate
  269.  *    declarations is bunged out onto the output stream.
  270.  *
  271.  *    Unfortunately, this implies that an entire function declaration
  272.  *    must be on a single line.... sorry to all those who don't use this
  273.  *    convention: I didn't feel up to writing a full C parser, or a
  274.  *    backtracking parser!
  275.  *
  276.  ****** The Grammar
  277.  *
  278.  *    The grammar is restricted; in particular, it omits:
  279.  *
  280.  *    1).    function parameters (use typedef!),
  281.  *    2).    array parameters (I use pointers instead),
  282.  *    3).    and struct parameters not concealed by #define's or typedef's.
  283.  *
  284.  *    function_declaration    = [ starred_id ] id '(' idlist ')' tslist
  285.  *    idlist            = empty | id list{ ',' id }
  286.  *    tslist            = list{ typespec } ( EOL | '{' )
  287.  *    typespec        = id starred_id list{ ',' starred_id } ';'
  288.  *    starred_id        = {'*'} id
  289.  *
  290.  ******* History
  291.  *
  292.  *    Version    Who    Date        Comments
  293.  *    =======    ===    ====        ========
  294.  *    1.0    dcw    16th Aug 1987    Wrote it
  295.  *    1.1    dcw    30th Aug 1987    Corrected spaces bug &
  296.  *                    added #ifdef LATTICE #else
  297.  *    1.2    dcw    9th Sep 1987    Used dcwos.h to determine HASPROTOS
  298.  *    1.3    dcw    25th Feb 1988    Added starred id for return type
  299.  *    XNX1.4    dcw    5th April 1988    Ported to Xenix
  300.  *                    made it accept declns eg. thingy() {..
  301.  *                    altered arg{c,v} interface.
  302.  *    BSD1.4    dcw    7th April 1988    Reverse ported to BSD
  303.  *    1.5    dcw    7th April 1988    Made if and while special cases in
  304.  *                    get_token
  305.  *    2.0    dcw    2nd July 1988    Made ready for releasing to news...
  306.  */
  307.  
  308.  
  309. #include "dcw.h"
  310.  
  311.  
  312. /* ----------------------- Data types ------------------------- */
  313.  
  314.  
  315. #define ID_LEN        50
  316. #define LINE_LEN    1024
  317.  
  318.  
  319. #define FDECL        struct anon1
  320. #define EL_IDLIST    struct anon2
  321. #define EL_TSLIST    struct anon3
  322.  
  323. #define IDLIST    EL_IDLIST *
  324. #define TSLIST    EL_TSLIST *
  325.  
  326. FDECL {
  327.     char    ftype[ID_LEN];
  328.     char    fname[ID_LEN];
  329.     IDLIST    formals;
  330.     TSLIST    ftypes;
  331. };
  332.  
  333. EL_IDLIST {
  334.     char    id[ID_LEN];
  335.     IDLIST    next;
  336. };
  337.  
  338. EL_TSLIST {
  339.     char    type[ID_LEN];
  340.     char    var[ID_LEN];
  341.     TSLIST    next;
  342. };
  343.  
  344.  
  345. /* --------------------- Forward declns ----------------------- */
  346. /*             Guess what generated these then ???              */
  347.  
  348.  
  349. #ifdef HASPROTOS
  350. extern void main( int , char ** );
  351. extern void usage( BOOL );
  352. extern void out_extern( FILE * , FDECL * , BOOL );
  353. extern void print_fdecl( FILE * , FDECL * );
  354. extern void prototype( FILE * , FDECL * , char * );
  355. extern int readline( FILE * , char * );
  356. extern void get_token( void );
  357. extern BOOL parse_function_decln( char * , FDECL * );
  358. extern BOOL parse_list_id( IDLIST * );
  359. extern BOOL parse_restof_ids( IDLIST * );
  360. extern BOOL parse_list_ts( TSLIST * );
  361. extern BOOL parse_typespec( TSLIST * );
  362. extern BOOL parse_starred_id( char * , char * );
  363. #else
  364. extern void main();
  365. extern void usage();
  366. extern void out_extern();
  367. extern void print_fdecl();
  368. extern void prototype();
  369. extern int readline();
  370. extern void get_token();
  371. extern BOOL parse_function_decln();
  372. extern BOOL parse_list_id();
  373. extern BOOL parse_restof_ids();
  374. extern BOOL parse_list_ts();
  375. extern BOOL parse_typespec();
  376. extern BOOL parse_starred_id();
  377. #endif
  378.  
  379.  
  380. /* ---------------------- Main program ------------------------ */
  381.  
  382.  
  383. void main( argc, argv ) int argc; char **argv;
  384. {
  385.     FILE    *in,*out;
  386.     FDECL    f;
  387.     char    line[LINE_LEN];
  388.     BOOL    origonly;
  389.  
  390.     usage( argc>1 && argc<=4 );
  391.  
  392.     origonly = ( strcmp( argv[1], "-f" ) == 0 );
  393.     if( origonly) {
  394.         int i;
  395.  
  396.         for( i=2; i<argc; i++ ) argv[i-1] = argv[i];
  397.         argc--;
  398.     }
  399.  
  400.     usage( argc > 1 );    /* still at least one argument left */
  401.  
  402.     in = fopen( argv[1], "r" );
  403.     ASSERT( in != NULL, ("Can't open '%s'\n",argv[1]) );
  404.  
  405.     if( argc == 2 ) {
  406.         out = stdout;
  407.     } else {
  408.         out = fopen( argv[2], "w" );
  409.         ASSERT( out != NULL, ("Can't create '%s'\n",argv[2]) );
  410.     }
  411.  
  412.     if( origonly ) {
  413.         while( readline( in, line ) != EOF ) {
  414.             if( parse_function_decln( line, &f ) ) {
  415.                 print_fdecl( out, &f );
  416.             }
  417.         }
  418.     } else {
  419.         fprintf( out, "#ifdef HASPROTOS\n" );
  420.         while( readline( in, line ) != EOF ) {
  421.             if( parse_function_decln( line, &f ) ) {
  422.                 out_extern( out, &f, TRUE );
  423.             }
  424.         }
  425.         fprintf( out, "#else\n" );
  426.         fseek( in, 0L, 0 );
  427.         while( readline( in, line ) != EOF ) {
  428.             if( parse_function_decln( line, &f ) ) {
  429.                 out_extern( out, &f, FALSE );
  430.             }
  431.         }
  432.         fprintf( out, "#endif\n" );
  433.     }
  434.     fclose( in );
  435.     fclose( out );
  436.     exit( 0 );
  437. }
  438.  
  439.  
  440. void usage(b) BOOL b;
  441. {
  442.     ASSERT( b, ("Usage: proto [-f] infile [outfile]\n") );
  443. }
  444.  
  445.  
  446. void out_extern( out, f, b ) FILE *out; FDECL *f; BOOL b;
  447. {
  448.     IDLIST  i;
  449.  
  450.     fprintf( out, "extern %s %s(", f->ftype, f->fname );
  451.     if( b ) {
  452.         if( f->formals ) {
  453.             prototype( out, f, f->formals->id );
  454.             for( i=f->formals->next; i; i=i->next ) {
  455.                 fprintf( out, "," );
  456.                 prototype( out, f, i->id );
  457.             }
  458.         } else {
  459.             fprintf( out, " void " );
  460.         }
  461.     }
  462.     fprintf( out, ");\n" );
  463. }
  464.  
  465.  
  466. /* print the original form of the function declaration */
  467.  
  468. void print_fdecl( out, f ) FILE *out; FDECL *f;
  469. {
  470.     IDLIST i;
  471.     TSLIST t;
  472.  
  473.     fprintf( out, "%s %s(", f->ftype, f->fname );
  474.     if( f->formals ) {
  475.         fprintf( out, "%s", f->formals->id );
  476.         for( i=f->formals->next; i; i=i->next ) {
  477.             fprintf( out, ", %s", i->id );
  478.         }
  479.     }
  480.     fprintf( out, ")" );
  481.     for( t=f->ftypes; t; t=t->next ) {
  482.         fprintf( out, " %s %s;", t->type, t->var );
  483.     }
  484.     fprintf( out, " \n" );
  485. }
  486.  
  487.  
  488. void prototype( out, f, name ) FILE *out; FDECL *f; char *name;
  489. {
  490.     TSLIST t;
  491.  
  492.     for( t=f->ftypes; t; t=t->next ) {
  493.         if( streq( name, t->var ) ) {
  494.             fprintf( out, " %s ", t->type );
  495.             return;
  496.         }
  497.     }
  498.     fprintf( stderr, "warning: %s has undeclared formal '%s' => integer\n",
  499.         f->fname, name );
  500. fprintf( out, " int" );
  501. }
  502.  
  503.  
  504. int readline( f, line ) FILE *f; char *line;
  505. {
  506.     int c;
  507.     char *p = line;
  508.  
  509.     c=getc(f);
  510.     if( c==EOF ) return c;
  511.     ungetc( c, f );
  512.     while( (c=getc(f)) != '\n' ) *p++ = c;
  513.     *p = '\0';
  514.     return p-line;
  515. }
  516.  
  517.  
  518. /* ----------------- Lexer routines ---------------------- */
  519.  
  520.  
  521. char *lex_line;
  522. char tokstr[100];
  523. enum token_type {
  524.     tID, tSTAR, tSEMI, tCOMMA, tOPEN, tCLOSE, tEOL, tBRACE, tERR
  525. } token;
  526.  
  527.  
  528. void get_token()
  529. {
  530.     char *s = tokstr;
  531.     char c;
  532.  
  533.     while( *lex_line == ' ' || *lex_line == '\t' ) lex_line++;
  534.     c = *lex_line++;
  535.     *s++ = c;
  536.     *s = '\0';
  537.  
  538.     switch( c ) {
  539.     case '\0' : token = tEOL      ; break;
  540.     case ','  : token = tCOMMA    ; break;
  541.     case ';'  : token = tSEMI     ; break;
  542.     case '*'  : token = tSTAR     ; break;
  543.     case '('  : token = tOPEN     ; break;
  544.     case '{'  : token = tBRACE; break;
  545.     case ')'  : token = tCLOSE    ; break;
  546.     default   :
  547.         if( !isalpha( c ) ) {
  548.             token = tERR;
  549.         } else {
  550.             while( (c = *lex_line)=='_'||isalnum(c) ) {
  551.                 *s++ = c; lex_line++;
  552.             }
  553.             *s = '\0';
  554.             if( strcmp(tokstr,"if") == 0
  555.             ||  strcmp(tokstr,"while") == 0
  556.             ||  strcmp(tokstr,"switch") == 0
  557.             ) {
  558.                 token = tERR;
  559.             } else {
  560.                 token = tID;
  561.             }
  562.         }
  563.     }
  564. }
  565.  
  566.  
  567. /* ------------------- Parser routines ------------------- */
  568.  
  569.  
  570. BOOL parse_function_decln( line, f ) char *line; FDECL *f;
  571. {
  572.     char stars   [ID_LEN];
  573.     char basetype[ID_LEN];
  574.  
  575.     lex_line = line;
  576.     get_token();
  577.     if( token != tID ) return FALSE;
  578.  
  579.     strcpy( basetype, tokstr );
  580.     get_token();
  581.     if( token == tOPEN ) {
  582.         strcpy( f->fname, basetype );
  583.         strcpy( f->ftype, "int" );
  584.     } else {
  585.         if( ! parse_starred_id( stars, f->fname ) ) return FALSE;
  586.  
  587.         if( *stars == '\0' ) {
  588.             strcpy( f->ftype, basetype );
  589.         } else {
  590.             sprintf( f->ftype, "%s %s", basetype, stars );
  591.         }
  592.         if( token != tOPEN ) return FALSE;
  593.     }
  594.     get_token();
  595.     if( ! parse_list_id( &(f->formals) ) || token != tCLOSE )
  596.         return FALSE;
  597.     get_token();
  598.     return parse_list_ts( &(f->ftypes) );
  599. }
  600.  
  601.  
  602. /* attempt to parse an idLIST [possibly empty] */
  603.  
  604. BOOL parse_list_id( ip ) IDLIST *ip;
  605. {
  606.     *ip = NULL;
  607.     if( token != tID ) return TRUE;
  608.     *ip = NEW( EL_IDLIST );
  609.     strcpy( (*ip)->id, tokstr );
  610.     get_token();
  611.     return parse_restof_ids( &((*ip)->next) );
  612. }
  613.  
  614.  
  615. BOOL parse_restof_ids( ip ) IDLIST *ip;
  616. {
  617.     *ip = NULL;
  618.     if( token != tCOMMA ) return TRUE;
  619.  
  620.     get_token();
  621.     if( token != tID ) return FALSE;
  622.  
  623.     *ip = NEW( EL_IDLIST );
  624.     strcpy( (*ip)->id, tokstr );
  625.     get_token();
  626.     return parse_restof_ids( &((*ip)->next) );
  627. }
  628.  
  629.  
  630. /*
  631.  * attempt to parse a list of typespecs [possibly empty]
  632.  * followed by tEOL or tBRACE
  633.  */
  634.  
  635. BOOL parse_list_ts( tp ) TSLIST *tp;
  636. {
  637.     TSLIST t;
  638.  
  639.     for(;;) {
  640.         *tp = NULL;
  641.         if( token==tEOL || token==tBRACE ) return TRUE;
  642.  
  643.         if( ! parse_typespec( tp ) ) return FALSE;
  644.         for( t = *tp; t->next; t=t->next );
  645.         tp = &(t->next);
  646.     }
  647.     /*NOTREACHED*/
  648. }
  649.  
  650.  
  651. BOOL parse_typespec( tp ) TSLIST *tp;
  652. {
  653.     char basetype[ID_LEN];
  654.     char stars   [ID_LEN];
  655.  
  656.     if( token != tID ) return FALSE;
  657.     strcpy( basetype, tokstr );
  658.  
  659.     for(;;) {
  660.         get_token();
  661.         *tp = NEW( EL_TSLIST );
  662.         if( ! parse_starred_id( stars, (*tp)->var ) ) return FALSE;
  663.  
  664.         if( *stars == '\0' ) {
  665.             strcpy( (*tp)->type, basetype );
  666.         } else {
  667.             sprintf( (*tp)->type, "%s %s", basetype, stars );
  668.         }
  669.  
  670.         if( token == tSEMI ) {
  671.             get_token();
  672.             return TRUE;
  673.         }
  674.         if( token != tCOMMA ) return FALSE;
  675.         tp = &((*tp)->next);
  676.     }
  677.     /*NOTREACHED*/
  678. }
  679.  
  680.  
  681. BOOL parse_starred_id( stars, id ) char *stars, *id;
  682. {
  683.     BOOL ok;
  684.  
  685.     while( token == tSTAR ) {
  686.         *stars++ = '*';
  687.         get_token();
  688.     }
  689.     *stars = '\0';
  690.     ok = token == tID;
  691.     if( ok ) {
  692.         strcpy( id, tokstr );
  693.         get_token();
  694.     }
  695.     return ok;
  696. }
  697. SHAR_EOF
  698. if test 10332 -ne "`wc -c < 'proto.c'`"
  699. then
  700.     echo shar: error transmitting "'proto.c'" '(should have been 10332 characters)'
  701. fi
  702. fi # end of overwriting check
  703. echo shar: extracting "'testproto'" '(134 characters)'
  704. if test -f 'testproto'
  705. then
  706.     echo shar: will not over-write existing file "'testproto'"
  707. else
  708. cat << \SHAR_EOF > 'testproto'
  709. int x()
  710. char *x(zz) int zz;
  711. char *x2((zz) int zz;
  712. char *x____32y(zz) int zz;
  713. helllo();
  714. wibblewobble ****eek(x,y,z) char **z; int x; {
  715. SHAR_EOF
  716. if test 134 -ne "`wc -c < 'testproto'`"
  717. then
  718.     echo shar: error transmitting "'testproto'" '(should have been 134 characters)'
  719. fi
  720. fi # end of overwriting check
  721. #    End of shell archive
  722. exit 0
  723.  
  724. ----------------------------------------------------------------------------
  725. Duncan White,           |       Flying is the art of aiming oneself
  726. Dept. Of Computing,     |       at the ground and missing.
  727. Imperial College,       |               -- Douglas Adams, So Long and Thanks
  728. London SW7, England     |                  for all the fish.
  729.